//
//  LSMenuViewController.m
//  LibraryStorm
//
//  Created by Enel@Lightning on 3/21/14.
//  Copyright (c) 2014 3ATeam. All rights reserved.
//

#import "LSMenuViewController.h"
#import "LSMainViewController.h"
#import "LSDetailViewController.h"
#import "LSCollectionViewController.h"

#import "UIImageView+AFNetworking.h"
#import "UIColor+HexString.h"
#import "SVPullToRefresh.h"

#import "LSMenuCell.h"
#import "BookCategory.h"

#import "LSSyncEngine.h"
#import "LSCoreDataController.h"

#define AvatarImageViewTag  1000
#define FacebookButtonTag   1001
static NSString * const MenuCellIdentifier = @"MenuCellId";
@interface LSMenuViewController () <LSSyncEngineDelegate>

@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong) NSArray *categories;
@property (nonatomic, strong) NSArray *features;
@property (nonatomic, strong) NSIndexPath *selectedIndexPath;
@property (nonatomic, copy) NSString *userFullName;
@property (nonatomic, copy) NSString *userImageName;
@end

@implementation LSMenuViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Default value of header section[0]
    self.userFullName = NSLocalizedString(@"Login", nil);
    self.userImageName = nil;
	// Do any additional setup after loading the view.
    // TODO: Custom background color
    [self.view setBackgroundColor:[UIColor colorWithHexString:Color_Orange_View]];
    [self.tableView setBackgroundColor:[UIColor whiteColor]];
    // TODO: Load Records From Core Data
    self.managedObjectContext = [[LSCoreDataController sharedInstance] newManagedObjectContext];
    
    [self loadRecordsFromCoreData];
    
    // TODO: Register notification when sync completed
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadRecords:) name:@"LSSyncEngineSyncCompleted" object:nil];
    [[LSSyncEngine sharedEngine] addObserver:self forKeyPath:@"syncInProgress" options:NSKeyValueObservingOptionNew context:nil];
    
    // TODO: Add pull to refresh on tableView
    __weak LSMenuViewController *weakSelf = self;
    [self.tableView addPullToRefreshWithActionHandler:^{
        [weakSelf updateRecordsLatest];
    }];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"LSSyncEngineSyncCompleted" object:nil];
    [[LSSyncEngine sharedEngine] removeObserver:self forKeyPath:@"syncInProgress"];
}

#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    if ([[segue identifier] isEqualToString:@"showCollectionViewId"]) {
        if (IS_DEVICE_IPAD) {
            if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]]) {
                UIPopoverController *popOverController = [(UIStoryboardPopoverSegue*)segue popoverController];
                UINavigationController *navigationViewController = [segue destinationViewController];
                if ([navigationViewController.topViewController isKindOfClass:[LSCollectionViewController class]]) {
                    LSCollectionViewController *collectionViewController = (LSCollectionViewController *)navigationViewController.topViewController;
                    collectionViewController.popOverController = popOverController;
                    collectionViewController.mm_drawerController = self.mm_drawerController;
                }
            }
        }
    }
}

#pragma mark - UITableViewDataSource
/**
 * Method name: numberOfSectionsInTableView
 * Description: Menu has 2 section. Section 1: Feature Section (Login, Favorite, History, Collection, Download Manager), Section 2: Category Section.
 * Parameters: UITableView
 */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 2;
}

/**
 * Method name: tableView:numberOfRowsInSection
 * Description: If section 2 (category section), add more 1 cell to section. Because list of category don't have identifier which reference to all category.
 * Parameters: UITableView, Section
 */
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == 0) {
        return self.features.count;
    }else {
        return self.categories.count+1;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    LSMenuCell *cell = [tableView dequeueReusableCellWithIdentifier:MenuCellIdentifier forIndexPath:indexPath];
    
    if (indexPath.section == 0) {
        if (indexPath.row < self.features.count) {
            NSString *featureName = [self.features objectAtIndex:indexPath.row];
            cell.titleLabel.text = featureName;
        }
    }else {
        // Add all category on top of section 2.
        if (indexPath.row == 0) {
            cell.titleLabel.text = NSLocalizedString(@"AllCategory", nil);
        }else {
            if (indexPath.row-1 < self.categories.count) {
                BookCategory *category = [self.categories objectAtIndex:indexPath.row-1];
                cell.titleLabel.text = category.name;
            }
        }
    }
    
    if (indexPath.section == self.selectedIndexPath.section && indexPath.row == self.selectedIndexPath.row) {
        // Show selectionStyle when row is selected.
        [self.tableView selectRowAtIndexPath:self.selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
    }
    
    return cell;
}

#pragma mark - UITableViewDelegate
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 44)];
    headerView.backgroundColor = [UIColor whiteColor];
    if (section == 0) {
        // Return avater image view, button to user login/logout facebook.
        UIImageView *avatarImageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, IS_DEVICE_IPAD ? 54 : 34, IS_DEVICE_IPAD ? 54 : 34)];
        [avatarImageView setBackgroundColor:[UIColor lightGrayColor]];
        [avatarImageView setTag:AvatarImageViewTag];
        avatarImageView.layer.cornerRadius = 5.0f;
        [avatarImageView setImage:nil];
        if (self.userImageName && self.userImageName.length > 0) {
            [avatarImageView setImageWithURL:[NSURL URLWithString:self.userImageName] placeholderImage:nil];
        }
        
        [headerView addSubview:avatarImageView];
        
        UIButton *facebookButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [facebookButton setTag:FacebookButtonTag];
        [facebookButton addTarget:self action:@selector(loginFacebook:) forControlEvents:UIControlEventTouchUpInside];
        [facebookButton setBackgroundColor:[UIColor clearColor]];
        [facebookButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
        [facebookButton setTitle:self.userFullName forState:UIControlStateNormal];
        [facebookButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        facebookButton.titleLabel.font = Roboto_Bold(IS_DEVICE_IPAD ? 22 : 16);
        facebookButton.frame = ({
            CGRect frame = facebookButton.frame;
            frame.origin.x = avatarImageView.frame.origin.x + avatarImageView.frame.size.width + 7;
            frame.origin.y = 0;
            frame.size.width = tableView.frame.size.width - frame.origin.x - 7;
            frame.size.height = IS_DEVICE_IPAD ? 64 : 44;
            frame;
        });
        [headerView addSubview:facebookButton];
    }else {
        // Return label
        UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, tableView.frame.size.width, IS_DEVICE_IPAD ? 64 : 44)];
        titleLabel.font = Roboto_Bold(IS_DEVICE_IPAD ? 22 : 16);
        titleLabel.textColor=[UIColor blackColor];
        titleLabel.backgroundColor = [UIColor clearColor];
        titleLabel.text= NSLocalizedString(@"Category", nil);
        [headerView addSubview:titleLabel];
    }
    
    return headerView;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return IS_DEVICE_IPAD ? 64 : 44;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return IS_DEVICE_IPAD ? 64 : 44;
}
/**
 * Method name: tableView:didSelectRowAtIndexPath
 * Description: Process data to show list of book at mainView. Pass LSMenuLeftType, CategoryId to main know which data to show. If mainView is detailView so that pop to listView.
 * Parameters: UITableView, NSIndexPath
 */
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.selectedIndexPath = indexPath;
    LSMainViewController *mainViewController = nil;
    if ([self.mm_drawerController.centerViewController isKindOfClass:[UINavigationController class]]) {
        // Get LSMainViewController on navigationController stack.
        if ([[(UINavigationController *)self.mm_drawerController.centerViewController topViewController] isKindOfClass:[LSMainViewController class]]) {
            mainViewController = (LSMainViewController *)[(UINavigationController *)self.mm_drawerController.centerViewController topViewController];
        }
        
        // If topViewController is DetailViewController so that pop to MainViewController
        if ([(UINavigationController *)self.mm_drawerController.centerViewController viewControllers].count > 1) {
            
            if (indexPath.section == 0) {
                if (indexPath.row == LSMenuLeftCollections && IS_DEVICE_IPAD) {
                    // Dont pop MainViewControler if click colection and iPad
                }else {
                    [(UINavigationController *)self.mm_drawerController.centerViewController popToRootViewControllerAnimated:YES];
                }
            }else {
                [(UINavigationController *)self.mm_drawerController.centerViewController popToRootViewControllerAnimated:YES];
            }
            
            if ([[(UINavigationController *)self.mm_drawerController.centerViewController viewControllers][0] isKindOfClass:[LSMainViewController class]]) {
                mainViewController = (LSMainViewController *)[(UINavigationController *)self.mm_drawerController.centerViewController viewControllers][0];
            }
        }
    }
    
    if (!mainViewController) {
        return;
    }
    
    // If user click collection tab so that present CollectionViewController (iPhone), popOver CollectionViewController (iPad)
    if (indexPath.section == 0) {
        if (indexPath.row == LSMenuLeftCollections) {
            // Show CollectionViewController
            [self performSegueWithIdentifier:@"showCollectionViewId" sender:nil];
            return;
        }else {
            // Show listOfBook on mainViewController
            [mainViewController showListBook:(LSMenuLeftType)indexPath.row withCategoryType:-1];
        }
    }else if (indexPath.section == 1) {
        // Default allCategory. Show all books on database.
        int categoryId = 0;
        if (indexPath.row > 0) {
            if (indexPath.row-1 < self.categories.count) {
                // Get categoryId to show books on this category.
                BookCategory *category = [self.categories objectAtIndex:indexPath.row-1];
                categoryId = category.categoryId.intValue;
                mainViewController.categoryManagedObjectID = [category objectID];
            }
        }
        // Method to process books.
        [mainViewController showListBook:LSMenuLeftCategory withCategoryType:categoryId];
    }
    
    // Hide menuLeft
    [self.mm_drawerController closeDrawerAnimated:YES completion:nil];
}

#pragma mark - Load and Update Records
/**
 * Method name: loadRecordsFromCoreData
 * Description: Get new all records from core data. Method is called when starting load viewController or after sync completed, update successful.
 * Parameters: nil
 */
- (void)loadRecordsFromCoreData
{
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"categoryId" ascending:YES];
    self.categories = [BookCategory getAllObjectsInContext:self.managedObjectContext withSortDescriptor:sortDescriptor resetContext:YES fetchLimit:0];
}

/**
 * Method name: Notification Observe
 * Description: Catch notification when sync completed
 * Parameters: nil
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"syncInProgress"]) {
        if (![LSSyncEngine sharedEngine].syncInProgress) {
            __weak LSMenuViewController *weakSelf = self;
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [weakSelf.tableView.pullToRefreshView stopAnimating];
            });
        }
    }
}

- (void)reloadRecords:(NSNotification *)note
{
    if ([[note object] isEqualToString:BOOK_CATEGORY]) {
        [self loadRecordsFromCoreData];
        [self.tableView reloadData];
        if (self.selectedIndexPath.section == 0 || (self.selectedIndexPath.section == 1 && self.selectedIndexPath.row < self.categories.count)) {
            // Category was changed by server. When user update category if selectedIndexPath < listOfCategory so that allow selectRowAtIndexPath
            [self.tableView selectRowAtIndexPath:self.selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
        }
    }
}

/**
 * Method name: updateRecordsLatest
 * Description: When user scroll to top and start update new category from service.
 * Parameters: nil
 */
- (void)updateRecordsLatest
{
    if (![kAppDelegate limitRequestForDay]) {
        [[LSSyncEngine sharedEngine] syncDataForRegisteredObject:BOOK_CATEGORY toUseUpdatedAtDate:YES toDeleteLocalRecords:NO withCategoryType:0 limitRecords:LIMIT_MAX_RECORDS skipOverRecords:0];
        [LSSyncEngine sharedEngine].delegate = self;
    }else {
        __weak LSMenuViewController *weakSelf = self;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [weakSelf.tableView.pullToRefreshView stopAnimating];
        });
    }
}

#pragma mark - Facebook
/**
 * Method name: loginFacebook
 * Description: Handle login function. If user was logined then logout and clean session. If user doesnt login then switch facebook app or brower to login.
 * Parameters: UIButton
 */
- (void)loginFacebook:(id)sender
{
    LSAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
    if (appDelegate.fbSession.isOpen) {
        // Show alertView confirm to logout
        LSAlertWithDelegate(NSLocalizedString(@"AlertTitle", nil), NSLocalizedString(@"LogoutFacebook", nil), self);
    }else {
        // Show alertView confirm to login
        LSAlertWithDelegate(NSLocalizedString(@"AlertTitle", nil), NSLocalizedString(@"LoginFacebook", nil), self);
    }
}

/**
 * Method name: updateLoginHeaderView
 * Description: Get information of user and update to header view
 * Parameters: nil
 */
- (void)updateLoginHeaderView
{
    // get the app delegate, so that we can reference the session property
    LSAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
    if (appDelegate.fbSession.isOpen) {
        [FBSession setActiveSession:appDelegate.fbSession];
        [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
            if (!error) {
                // Get user's information
                self.userFullName = [appDelegate decodeString:result key:@"name"];
                NSString *userId = [appDelegate decodeString:result key:@"id"];
                self.userImageName = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture", userId];
                [self setContentForHeaderView];
            }
        }];
    }else {
        [FBSession setActiveSession:nil];
        self.userFullName = NSLocalizedString(@"Login", nil);
        self.userImageName = nil;
        [self setContentForHeaderView];
    }
}

/**
 * Method name: setContentForHeaderView
 * Description: Show avatar and name of user on headerView.
 * Parameters: nil
 */
- (void)setContentForHeaderView
{
    UIImageView *avatarImageView = (UIImageView *)[self.view viewWithTag:AvatarImageViewTag];
    if (avatarImageView) {
        [avatarImageView setImage:nil];
        if (self.userImageName && self.userImageName.length > 0) {
            [avatarImageView setImageWithURL:[NSURL URLWithString:self.userImageName] placeholderImage:nil];
        }
    }
    UIButton *facebookButton = (UIButton *)[self.view viewWithTag:FacebookButtonTag];
    if (facebookButton) {
        [facebookButton setTitle:self.userFullName forState:UIControlStateNormal];
    }
}

#pragma mark - Alert view delegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != alertView.cancelButtonIndex) {
        // get the app delegate so that we can access the session property
        LSAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
        // this button's job is to flip-flop the session from open to closed
        if (appDelegate.fbSession.isOpen) {
            // if a user logs out explicitly, we delete any cached token information, and next
            // time they run the applicaiton they will be presented with log in UX again; most
            // users will simply close the app or switch away, without logging out; this will
            // cause the implicit cached-token login to occur on next launch of the application
            [appDelegate.fbSession closeAndClearTokenInformation];
            [self updateLoginHeaderView];
        } else {
            if (!appDelegate.fbSession || appDelegate.fbSession.state != FBSessionStateCreated) {
                // Create a new, logged out session.
                appDelegate.fbSession = [[FBSession alloc] init];
            }
            
            // if the session isn't open, let's open it now and present the login UX to the user
            [appDelegate.fbSession openWithCompletionHandler:^(FBSession *session,
                                                               FBSessionState status,
                                                               NSError *error) {
                // and here we make sure to update our UX according to the new session state
                [self updateLoginHeaderView];
            }];
        }
    }
}

#pragma mark - Override getter method
- (NSIndexPath *)selectedIndexPath
{
    if (!_selectedIndexPath) {
        // If _selectedIndexPath isn't init, default is indexPath[1,0]
        _selectedIndexPath = [NSIndexPath indexPathForRow:0 inSection:1];
    }
    
    return _selectedIndexPath;
}

- (NSArray *)features
{
    if (!_features) {
        _features = @[NSLocalizedString(@"Favorites", nil), NSLocalizedString(@"Collections", nil), NSLocalizedString(@"History", nil), NSLocalizedString(@"Downloads", nil)];
    }
    
    return _features;
}

#pragma mark - Sync Engine Delegate
/**
 * Method name: Sync Engine
 * Description: Update new category if changed.
 * Parameters: LSSyncEngine, ClassName, useUpdatedAtDate
 */
- (void)syncEngine:(LSSyncEngine *)syncEngine forRegisteredObject:(NSString *)className toUseUpdatedAtDate:(BOOL)useUpdatedAtDate
{
    if ([className isEqualToString:BOOK_CATEGORY]) {
        // When sync completed, load again records from core data and reload tableView
        [self loadRecordsFromCoreData];
        [self.tableView reloadData];
        if (self.selectedIndexPath.section == 0 || (self.selectedIndexPath.section == 1 && self.selectedIndexPath.row < self.categories.count)) {
            [self.tableView selectRowAtIndexPath:self.selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
        }
        
        [kAppDelegate increaseCountOfRequestForDay];
    }
}

- (void)syncEngine:(LSSyncEngine *)syncEngine withError:(NSError *)error toUseUpdatedAtDate:(BOOL)useUpdatedAtDate
{
    // NSLog: Sync Error
    __weak LSMenuViewController *weakSelf = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [weakSelf.tableView.pullToRefreshView stopAnimating];
    });
}
@end
